package com.zyao89.view.zweb.utils;

import java.lang.reflect.*;

/**
 * @author Zyao89
 * 2017/11/8.
 */
public class Utils {
    public static <T> void validateServiceInterface(Class<T> service) {
        if (!service.isInterface()) {
            throw new IllegalArgumentException("API declarations must be interfaces.");
        }

        if (service.getInterfaces().length > 0) {
            throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
        }
    }

    public static Class<?> getRawType(Type type) {
        checkNotNull(type, "type == null");

        if (type instanceof Class<?>) {
            // TYPE is a normal class.
            return (Class<?>) type;
        }
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;

            // I'm not exactly sure why getRawType() returns TYPE instead of Class. Neal isn't either but
            // suspects some pathological case related to nested classes exists.
            Type rawType = parameterizedType.getRawType();
            if (!(rawType instanceof Class)) {
                throw new IllegalArgumentException();
            }
            return (Class<?>) rawType;
        }
        if (type instanceof GenericArrayType) {
            Type componentType = ((GenericArrayType) type).getGenericComponentType();
            return Array.newInstance(getRawType(componentType), 0).getClass();
        }
        if (type instanceof TypeVariable) {
            // We could use the variable's bounds, but that won't work if there are multiple. Having a raw
            // type that's more general than necessary is okay.
            return Object.class;
        }
        if (type instanceof WildcardType) {
            return getRawType(((WildcardType) type).getUpperBounds()[0]);
        }

        throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " + "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName());
    }

    public static <T> T checkNotNull(T object, String message) {
        if (object == null) {
            throw new NullPointerException(message);
        }
        return object;
    }

    public static boolean checkSupportType(Type parameterType) {
        if (parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)) {
            return true;
        }
        if (parameterType.equals(Character.class) || parameterType.equals(char.class)) {
            return true;
        }
        if (parameterType.equals(Byte.class) || parameterType.equals(byte.class)) {
            return true;
        }
        if (parameterType.equals(Double.class) || parameterType.equals(double.class)) {
            return true;
        }
        if (parameterType.equals(Float.class) || parameterType.equals(float.class)) {
            return true;
        }
        if (parameterType.equals(Integer.class) || parameterType.equals(int.class)) {
            return true;
        }
        if (parameterType.equals(Long.class) || parameterType.equals(long.class)) {
            return true;
        }
        if (parameterType.equals(Short.class) || parameterType.equals(short.class)) {
            return true;
        }
        if (parameterType.equals(String.class)) {
            return true;
        }
        return false;
    }
}
